﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using Local = Microsoft.Forums.OfflineStore;
using Web = Microsoft.Forums.MicrosoftForumsProvider.Forums;
using System.Diagnostics;
using Microsoft.Forums.ForumsProvider;

namespace Microsoft.Forums.MicrosoftForumsProvider
{
    /// <summary>
    /// Provides methods to convert from the Object Model of the Web Service to 
    /// the object model of the Forums Client
    /// </summary>
    public static class DomainObjectConverters
    {

        /// <summary>
        /// Convert ForumResult(web) to Forum(local) object
        /// </summary>
        /// <param name="forumResult">Web service forum object</param>
        /// <returns>Forums client forum object</returns>
        public static Local.Forum Convert(Web.BriefForum forumResult)
        {
            if (forumResult == null) throw new ArgumentNullException("forumResult", "forumResult must not be null");

            var forum = new Local.Forum();
            CopyTo(forumResult, forum);
            return forum;
        }

        /// <summary>
        /// Copy the ForumResult(web) to Forum(local) object
        /// </summary>
        /// <param name="forumResult">From Web service forum object</param>
        /// <param name="forum">To Forums Client forum object</param>
        public static void CopyTo(Web.BriefForum forumResult, Local.Forum forum)
        {
            if (forumResult == null) throw new ArgumentNullException("forumResult", "forumResult must not be null");
            if (forum == null) throw new ArgumentNullException("forum", "forum must not be null");

            // Data
            forum.Id = forumResult.ForumId;
            forum.Name = forumResult.UniqueName;
            forum.ForumServiceProviderId = MicrosoftForumsServiceProvider.ProviderGuid;
            forum.ForumType = (int)forumResult.GroupType;
            forum.Description = forumResult.Description;
            forum.Language = forumResult.Language;
            forum.DisplayName = forumResult.DisplayName;
            forum.ModifiedOn = forumResult.ModifiedOn;
            // Properties
            forum.IsBugTracked = forumResult.BugTracking;
            forum.IsPrivate = forumResult.IsPrivate;
            forum.IsLocked = forumResult.IsLocked;
        }


        /// <summary>
        /// Convert ThreadResult(web) to Thread(local) object
        /// </summary>
        /// <param name="threadResult">Web service thread object</param>
        /// <returns>Forums client thread object</returns>
        public static Local.Thread Convert(Web.BriefThread threadResult)
        {
            if (threadResult == null) throw new ArgumentNullException("threadResult", "threadResult must not be null");

            var thread = new Local.Thread();
            CopyTo(threadResult, thread);
            return thread;
        }

        /// <summary>
        /// Copy the ThreadResult(web) to Thread(local) object
        /// </summary>
        /// <param name="threadResult">From Web service thread object</param>
        /// <param name="thread">TO Forums Client thread object</param>
        public static void CopyTo(Web.BriefThread threadResult, Local.Thread thread)
        {
            if (threadResult == null) throw new ArgumentNullException("threadResult", "threadResult must not be null");
            if (thread == null) throw new ArgumentNullException("thread", "thread must not be null");

            // Data
            thread.Id = threadResult.Id;
            thread.ThreadType = (int)threadResult.ThreadType;
            thread.Topic = threadResult.Topic;
            thread.ForumId = threadResult.ForumId;

            thread.CreatedOn = threadResult.CreatedOn;
            if (threadResult.CreatedBy != null)
            {
                thread.CreatedById = threadResult.CreatedBy.Id;
            }
            else
            {
                throw new InvalidOperationException("threadResult.CreatedBy cannot be null");
            }

            thread.ModifiedOn = threadResult.ModifiedOn;

            thread.LastReplyOn = threadResult.LastReplyDate;
            thread.LastReplyId = threadResult.LastReplyId;

            // Stats
            thread.TotalReplies = threadResult.TotalReplies;
            thread.TotalViews = threadResult.TotalViews;
            thread.RootPostId = threadResult.RootMessageId;
            // Properties
            // THe new version of the API has these omitted but we want them back!
            //thread.HasDeleted = threadResult.HasDeleted;
            //thread.HasAbusive = threadResult.HasAbusive;
            //thread.HasProposedAnswers = threadResult.HasProposedAnswers;
            thread.IsHelpful = threadResult.IsHelpful;
            thread.IsSticky = threadResult.IsSticky;
            thread.StickyDate = threadResult.StickyDate;
            thread.IsAnswered = threadResult.IsAnswered;
            thread.IsLocked = threadResult.IsLocked;



        }

        /// <summary>
        /// Convert MessageResult(web) to Post(local) object
        /// </summary>
        /// <param name="messageResult">Web service post object</param>
        /// <param name="forumId">The forum id.</param>
        /// <returns>Forums client post object</returns>
        public static Local.Post Convert(Web.BriefMessage messageResult, Guid forumId)
        {
            if (messageResult == null) throw new ArgumentNullException("messageResult", "messageResult must not be null");

            var post = new Local.Post();
            CopyTo(messageResult, post);
            post.ForumId = forumId;
            return post;
        }

        /// <summary>
        /// Copy the MessageResult(web) to Post(local) object
        /// </summary>
        /// <param name="messageResult">From Web service post object</param>
        /// <param name="post">To Forums Client post object</param>
        public static void CopyTo(Web.BriefMessage messageResult, Local.Post post)
        {
            if (messageResult == null) throw new ArgumentNullException("messageResult", "messageResult must not be null");
            if (post == null) throw new ArgumentNullException("post", "post must not be null");

            // Data
            post.Id = messageResult.Id;
            post.Body = messageResult.Body;
            post.Subject = messageResult.Subject;
            post.ThreadId = messageResult.DiscussionId;
            post.PostType = (int)messageResult.MessageType;
            post.CreatedOn = messageResult.CreatedOn;
            post.ParentId = messageResult.ParentId;
            post.CreatedBy = Convert(messageResult.CreatedBy);
            post.ModifiedOn = messageResult.ModifiedDate == DateTime.MinValue ? post.CreatedOn : messageResult.ModifiedDate;
            post.ModifiedBy = messageResult.ModifiedBy == null ? null : Convert(messageResult.ModifiedBy);

            // Properties
            post.IsAbusive = messageResult.IsAbusive;
            post.IsAnswer = messageResult.IsAnswer;
            post.TotalReplies = messageResult.TotalReplies;

        }



        /// <summary>
        /// Convert UserDataResult(web) to User(local) object
        /// </summary>
        /// <param name="userDataResult">Web service user object</param>
        /// <returns>Forums client user object</returns>
        public static Local.User Convert(Web.BriefUser userDataResult)
        {
            if (userDataResult == null) throw new ArgumentNullException("userDataResult", "userDataResult must not be null");

            var user = new Local.User();
            CopyTo(userDataResult, user);
            return user;
        }

        /// <summary>
        /// Copy the UserDataResult(web) to User(local) object
        /// </summary>
        /// <param name="userDataResult">From Web service post object</param>
        /// <param name="user">To Forums Client user object</param>
        public static void CopyTo(Web.BriefUser userDataResult, Local.User user)
        {
            if (userDataResult == null) throw new ArgumentNullException("userDataResult", "userDataResult must not be null");
            if (user == null) throw new ArgumentNullException("user", "user must not be null");

            user.Id = userDataResult.Id;
            user.DisplayName = userDataResult.DisplayName;
            user.IsMsft = userDataResult.IsMsft;
            user.IsMvp = userDataResult.IsMvp;
            user.PostsCount = userDataResult.PostsCount;
            user.AnswersCount = userDataResult.AnswersCount;
            user.Stars = userDataResult.Stars;
            user.Points = userDataResult.Points;
            user.JoinedDate = userDataResult.JoinedDate;
            user.LastActiveDate = userDataResult.LastActiveDate;
            user.IsInappropriate = userDataResult.IsInappropriate;


        }

        /// <summary>
        /// Convert UserDataResult(web) to DetailedUser object
        /// </summary>
        /// <param name="userDataResult">Web service user object</param>
        /// <returns>Forums client DetailedUser object</returns>
        public static DetailedUser Convert(Web.User userDataResult)
        {
            if (userDataResult == null) throw new ArgumentNullException("userDataResult", "userDataResult must not be null");

            var detailedUser = new DetailedUser();
            CopyTo(userDataResult, detailedUser);
            return detailedUser;
        }

        /// <summary>
        /// Copy the UserDataResult(web) to DetailedUser object
        /// </summary>
        /// <param name="userDataResult">From Web service post object</param>
        /// <param name="detailedUser">To Forums Client DetailedUser object</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
        public static void CopyTo(Web.User userDataResult, DetailedUser detailedUser)
        {
            if (userDataResult == null) throw new ArgumentNullException("userDataResult", "userDataResult must not be null");
            if (detailedUser == null) throw new ArgumentNullException("detailedUser", "detailedUser must not be null");

            // Copy base class members first
            CopyTo((Web.BriefUser)userDataResult, (Local.User)detailedUser);

            if(userDataResult.Permissions != null)
            {
                detailedUser.Permissions = userDataResult.Permissions.ConvertAll(u => Convert(u));
            }
        }


        /// <summary>
        /// Converts the specified web permission.
        /// </summary>
        /// <param name="webPermission">The web permission.</param>
        /// <returns></returns>
        public static Permission Convert(Web.ForumPermission webPermission)
        {
            if (webPermission == null) throw new ArgumentNullException("webPermission", "webPermission must not be null");

            var permission = new Permission();
            CopyTo(webPermission, permission);
            return permission;
        }

        /// <summary>
        /// Copies  ForumPermission to Permission.
        /// </summary>
        /// <param name="webPermission">The web permission.</param>
        /// <param name="permission">The permission.</param>
        public static void CopyTo(Web.ForumPermission webPermission, Permission permission)
        {
            if (webPermission == null) throw new ArgumentNullException("webPermission", "webPermission must not be null");
            if (permission == null) throw new ArgumentNullException("permission", "permission must not be null");

            permission.CanMarkAnswers = webPermission.CanMarkAnswers;
            permission.CanPost = webPermission.CanPost;
            permission.CanViewAbusive = webPermission.CanViewAbusive;
            permission.CanViewDeleted = webPermission.CanViewDeleted;
            permission.CanViewMessageHistory = webPermission.CanViewMessageHistory;
            permission.ForumId = webPermission.ForumId;
            permission.IsAnswerer = webPermission.IsAnswerer;
            permission.IsModerator = webPermission.IsModerator;
            permission.IsOwner = webPermission.IsOwner;
        }

    }
}
